﻿
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;

namespace ZFBActivation.Core
{
    public static class JsonHelper
    {
        private static readonly JsonSerializerSettings jsetting = new JsonSerializerSettings {
            DefaultValueHandling = DefaultValueHandling.Ignore,
            Converters = new List<Newtonsoft.Json.JsonConverter> { new HexLongConverter(), new DateTimeConverter() }
        };

        private static readonly JsonSerializerSettings jsettingFormatting = new JsonSerializerSettings {
            Formatting = Formatting.Indented,
            DefaultValueHandling = DefaultValueHandling.Ignore,
            Converters = new List<Newtonsoft.Json.JsonConverter> { new HexLongConverter(), new DateTimeConverter() }
        };

        private static readonly JsonSerializerSettings jsettingFormattingDefaultValue = new JsonSerializerSettings {
            Formatting = Formatting.Indented,
            Converters = new List<Newtonsoft.Json.JsonConverter> { new HexLongConverter(), new DateTimeConverter() }
        };

        private static readonly JsonSerializerSettings jsettingDefaultValue = new JsonSerializerSettings {
            Converters = new List<Newtonsoft.Json.JsonConverter> { new HexLongConverter(), new DateTimeConverter() }
        };


        static JsonHelper() {


        }

        public static T FastClone<T>(this T value) {
            return value.ToJson().ToObject<T>();
        }

        public static K FastClone<K>(this Object value) {
            return value.ToJson().ToObject<K>();
        }

        public static T ToObject<T>(this string value) {
            if (string.IsNullOrWhiteSpace(value)) return default;
            return JsonConvert.DeserializeObject<T>(value, jsetting);
        }

        public static string ToJson(this object value, bool isFormat = false) {
            if (value == null) return string.Empty;

            if (isFormat)
                return JsonConvert.SerializeObject(value, jsettingFormatting);
            return JsonConvert.SerializeObject(value, jsetting);
        }



        public static string ToJsonDefaultValue(this object value, bool isFormat = false, DefaultValueHandling defaultValueHandling = DefaultValueHandling.Populate) {
            if (value == null) return string.Empty;

            if (isFormat)
                return JsonConvert.SerializeObject(value, jsettingFormattingDefaultValue);
            return JsonConvert.SerializeObject(value, jsettingDefaultValue);
        }
    }

    public class HexLongConverter : Newtonsoft.Json.JsonConverter
    {
        public override void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) {
            // 由于CanConvert过滤，数据类型只可能是long或ulong
            // 统一转换成long类型处理
            var v = value is ulong ? (long)(ulong)value : (long)value;
            writer.WriteValue(v.ToString());
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) {
            // 调用ToInt64扩展将字符串转换成long型
            // ToInt64扩展方法后附
            var v = long.Parse(reader.Value.ToString());
            // 将v转换成实际需要的类型 ulong 或 long(不转换)
            return typeof(ulong) == objectType ? (object)(ulong)v : v;
        }

        public override bool CanConvert(Type objectType) {
            // 只处理long和ulong两种类型的数据
            switch (objectType.FullName) {
                case "System.Int64":
                case "System.UInt64":
                    return true;

                default:
                    return false;
            }
        }
    }


    public class DateTimeConverter : Newtonsoft.Json.JsonConverter
    {
        public override bool CanConvert(Type objectType) {
            switch (objectType.FullName) {
                case "System.DateTime":
                    return true;

                default:
                    return false;
            }
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) {
            return DateTime.Parse(reader.Value.ToString());
        }

        public override void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) {
            if (value is DateTime date) {
                writer.WriteValue(date.ToString("yyyy-MM-dd HH:mm:ss"));
            }
        }
    }




}